package org.nanhill.gecko;

import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class DownloadQueue implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -5926750982570131515L;

	private SpiderConfig config;

	private List<URLToDownload> interestingURLsToDownload;

	private List<URLToDownload> averageURLsToDownload;

	private List<URLToDownload> boringURLsToDownload;

	private Set<URL> urlsInQueue;

	public DownloadQueue(SpiderConfig config) {
		this.config = config;
		interestingURLsToDownload = new ArrayList<URLToDownload>();
		averageURLsToDownload = new ArrayList<URLToDownload>();
		boringURLsToDownload = new ArrayList<URLToDownload>();
		urlsInQueue = new HashSet<URL>();
	}

	public void queueURL(URLToDownload url) {
		URL u = url.getURL();
		if (urlsInQueue.contains(u)) {
			return;
		}

		if (config.isInteresting(u)) {
			if (config.isDepthFirstSearch()) {
				interestingURLsToDownload.add(0, url);
			} else {
				interestingURLsToDownload.add(url);
			}
		} else if (config.isBoring(u)) {
			if (config.isDepthFirstSearch()) {
				boringURLsToDownload.add(0, url);
			} else {
				boringURLsToDownload.add(url);
			}
		} else {
			if (config.isDepthFirstSearch()) {
				averageURLsToDownload.add(0, url);
			} else {
				averageURLsToDownload.add(url);
			}
		}

		urlsInQueue.add(u);
	}

	public void queueURLs(Collection urls) {
		for (Iterator i = urls.iterator(); i.hasNext();) {
			URLToDownload u2d = (URLToDownload) i.next();
			queueURL(u2d);
		}
	}

	public URLToDownload getNextInQueue() {
		if (interestingURLsToDownload.size() > 0) {
			return returnURLFrom(interestingURLsToDownload);
		} else if (averageURLsToDownload.size() > 0) {
			return returnURLFrom(averageURLsToDownload);
		} else if (boringURLsToDownload.size() > 0) {
			return returnURLFrom(boringURLsToDownload);
		} else {
			return null;
		}
	}

	private URLToDownload returnURLFrom(List urlList) {
		URLToDownload u2d = (URLToDownload) urlList.get(0);
		urlList.remove(0);
		urlsInQueue.remove(u2d.getURL());
		return u2d;
	}

	public int size() {
		return interestingURLsToDownload.size() + averageURLsToDownload.size()
				+ boringURLsToDownload.size();
	}

	public String toString() {
		return size() + " URLs";
	}

} // End class DownloadQueue
